package cn.mw.cmdb.view;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.MwCMDBConfigInfo;
import cn.mw.cmdb.enums.TableViewTypeEnum;
import cn.mw.cmdb.enums.ZabbixAssetsStatusEnum;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.MwCMDBConfigImpl;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.microMonitorCommon.api.cmdb.TableIdEnum;
import cn.mw.microMonitorCommon.api.cmdb.TreeView;
import cn.mw.microMonitorCommon.api.common.Constants;
import cn.mw.microMonitorCommon.util.SpringUtils;
import cn.mw.microMonitorCommon.util.TreeUtils;
import cn.mw.microMonitorCommon.utils.DatabaseUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static cn.mw.cmdb.enums.ModelConfigKeyEnum.systemDevType;
import static cn.mw.cmdb.param.SystemDevTypeEnum.scBankSystemDev;

@Slf4j
public class TreeViewConverter implements ViewConvert<List<TreeView>, List<TreeView>> {
    private static final String RootName = "/";
    private static final Long RootId = 99999999L;

    private static final String statusType = "status";

    @Override
    public List<TreeView> convert(List<TreeView> list, ViewConvertContext context) throws Exception {
        Map<Object, TreeViewObject> map = new HashMap<>();
        //获取运行环境值
        CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
        MwCMDBConfigImpl configServer = (MwCMDBConfigImpl) cmdbServiceManage.getModelService(MwCMDBConfigImpl.ID);
        MwCMDBConfigInfo cmdbConfigInfo = configServer.doSelectByKey(systemDevType.name());
        Object configValue = cmdbConfigInfo.getConfigValue();
        String systemType = "";
        if (configValue instanceof String) {
            systemType = (String) configValue;
        }
        log.info("systemType::" + systemType);
        String baseGroupId = SpringUtils.getPropertiesValue("base.groupId");
        String videoGroupId = SpringUtils.getPropertiesValue("base.video.groupId");
        List<TreeView> ret = new ArrayList<>();
        for (TreeView treeView : list) {
            TreeViewObject treeViewObject = new TreeViewObject();
            treeViewObject.setId(treeView.getId().toString());

            treeViewObject.setItemName(treeView.getItemName());
            treeViewObject.setType(treeView.getType());
            treeViewObject.setCount(treeView.getCount());
            treeViewObject.setItemAssetsStatus(treeView.getItemAssetsStatus());
            treeViewObject.setChildStatus(treeView.getChildStatus());
            treeViewObject.setSortNum(treeView.getSortNum());
            //设置表头数据
            treeViewObject.headerTypeSetting(treeView, context, baseGroupId, videoGroupId);
            treeViewObject.setViewType(treeView.getViewType());
            map.put(treeView.getId().toString(), treeViewObject);
            //多个parentId的情况,需要分解
            if (null == treeView.getParentId()) {
                ret.add(treeViewObject);
            } else {
                Object parentIdObj = treeView.getParentId();
                if (parentIdObj instanceof List) {
                    List parents = (List) parentIdObj;
                    cloneTreeViewObjectForParentId(treeViewObject, parents, ret);
                } else {
                    treeViewObject.setParentId(treeView.getParentId());
                }
            }
        }
        List<TreeViewObject> lists = map.values().stream().toList();
        List<TreeViewObject> sortList = lists.stream().sorted(Comparator.comparing(TreeView::getItemName)).collect(Collectors.toList());

        for (TreeViewObject treeView : sortList) {
            if (null != treeView.getParentId()) {
                TreeViewObject treeViewObject = map.get(treeView.getParentId().toString());
                if (null != treeViewObject) {
                    if (TableViewTypeEnum.videoOverview.getCode().equals(treeViewObject.getViewType())) {
                        treeView.setViewType(TableViewTypeEnum.videoList.getCode());
                    }
                    treeViewObject.addTreeView(treeView);
                }
            }
        }

        for (TreeViewObject treeView : sortList) {
            if (CollectionUtils.isEmpty(treeView.getChilds()) && CollectionUtils.isNotEmpty(treeView.getChildStatus())) {
                Map<String, Long> status2CountMap = treeView.getChildStatus().stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
                TreeViewObject child;
                List<String> statusList = new ArrayList<>(status2CountMap.keySet());
                statusList.sort(Comparator.comparingInt(ZabbixAssetsStatusEnum::getAssetsStatusCode));
                for (String status : statusList) {
                    child = new TreeViewObject();
                    child.setType(statusType);
                    child.setHeaderType(treeView.getHeaderType());
                    child.setItemAssetsStatus(status);
                    child.setItemName(status);
                    child.setId(treeView.getId() + Constants.ID_SPLIT + CMDBTool.getFieldName(InstanceInfo::getItemAssetsStatus) + Constants.PROPERTY_SPLIT +
                            (StringUtils.equals(status, ZabbixAssetsStatusEnum.UNKNOWN.getName()) ? "" : status));
                    child.setCount(Math.toIntExact(status2CountMap.getOrDefault(status, 0L)));
                    treeView.addTreeView(child);
                }
            }
            treeView.setChildStatus(null);
        }
        if (context !=null && context.getHideStatusFlag() != null && context.getHideStatusFlag()) {
            for (TreeView treeView : ret) {
                TreeViewObject treeViewObject = (TreeViewObject) treeView;
                treeViewObject.removeChildByType(TableIdEnum.status.getCode());
            }
        }
        //四川环境
        if(scBankSystemDev.name().equals(systemType)){
            sortList(ret);
        }else{
            TreeUtils.sortTree(ret, DatabaseUtils.getFieldName(TreeViewObject::getChilds), DatabaseUtils.getFieldName(TreeViewObject::getItemName));
        }
        return ret;
    }


    private void cloneTreeViewObjectForParentId(TreeViewObject treeView, List<Object> parentIds, List<TreeView> dest) {
        treeView.setParentId(parentIds.get(0));
        for (int i = 1; i < parentIds.size(); i++) {
            TreeViewObject treeViewObject = new TreeViewObject();
            treeViewObject.setId(treeView.getId());
            treeViewObject.setParentId(parentIds.get(i));
            treeViewObject.setItemName(treeView.getItemName());
            treeViewObject.setType(treeView.getType());
            dest.add(treeViewObject);
        }
    }



    // 递归排序方法
    public static void sortList(List<TreeView> list) {
        if (list == null) {
            return;
        }
        // 排序当前列表
        Collections.sort(list, new Comparator<TreeView>() {
            @Override
            public int compare(TreeView val1, TreeView val2) {
                if(val1 instanceof TreeViewObject && val2 instanceof TreeViewObject){
                    TreeViewObject t1 = (TreeViewObject) val1;
                    TreeViewObject t2 = (TreeViewObject) val2;
                    if (t1.getSortNum() != null && t2.getSortNum() != null) {
                        return t1.getSortNum().compareTo(t2.getSortNum());
                    } else if (t1.getSortNum() != null) {
                        return -1; // t1 有 sort 值，排在前面
                    } else if (t2.getSortNum() != null) {
                        return 1; // t2 有 sort 值，排在前面
                    } else {
                        return t1.getItemName().compareTo(t2.getItemName());
                    }
                }
                return 0;
            }
        });

        // 递归排序 childData
        for (TreeView item : list) {
            if(item instanceof TreeViewObject){
                TreeViewObject itemObj = (TreeViewObject)item;
                List<TreeView> childs = itemObj.getChilds();
                sortList(childs);
            }
        }
    }


}
